import type { Writable } from 'svelte/store';

export type EditingColDataState = {
  oldValue: string | number;
  newValue: string | number;
  valid: boolean;
  tip: string;
}

export type EditingRowDataState = {
  [k: string]: EditingColDataState
}

export type TableContext = {
  isDirty$: Writable<Boolean>;
  isEditingRowDataState$: Writable<EditingRowDataState>;
}

export type InlineOperateOption<T> = {
  text: string;
  handler: () => T
}

export enum CellType {
  Text = 0,
  Button = 1,
  Icon = 2,
  Link = 3
}

export enum CellEditComponentType {
  None = 0,
  Input = 1,
  Dropdown = 2,
  CheckBox = 3,
}

export enum Align {
  Left = "left",
  Center = "center",
  Right = "right",
}

export type Action = (o: any) => void;

export type CheckCellEditComponentTypeFunc = (o: any) => CellEditComponentType;

export type CheckCellOptionTypeFunc<T> = (o: any) => T;

export type Matcher = (o: any) => boolean;

export type CellOptions = {
  type?: CellType;
  align?: Align;
  icon?: string | CheckCellOptionTypeFunc<string>;
  text?: string | CheckCellOptionTypeFunc<string>;
  editable?: boolean;
  editType?: CellEditComponentType | CheckCellEditComponentTypeFunc;
  editOption?: {
    required?: boolean
  };
  buttonOption?: {
    action?: Action;
    
  };
  dropdownOption?: {
    dropdownEntries?: Record<string, string>; // value,text
    dropdownHeight?: number;
  };
  linkOption?: {
    href: string | CheckCellOptionTypeFunc<string>;
    matcher?: Matcher;
  }
};

export const isCheckCellEditComponentTypeFunc = (t: CellEditComponentType | CheckCellEditComponentTypeFunc): t is CheckCellEditComponentTypeFunc => {
  return typeof t === "function"
}

export const isCheckCellContentTypeFunc = <T>(t: T | CheckCellOptionTypeFunc<T>): t is CheckCellOptionTypeFunc<T> => {
  return typeof t === "function"
}

export const getCellContentType = <T>(o: T | CheckCellOptionTypeFunc<T>, rowData: any): T => {
  if (isCheckCellContentTypeFunc(o)) {
    return o(rowData)
  } 
  return o;
}

export type Column = {
  key: string;
  title?: string;
  headAlign?: Align;
  width?: number;
  classes?: string;
  options?: CellOptions;
};

export type DataRow<T> = {
  children?: T[]
}

export type DataSource<T extends DataRow<T>> = {
  rows: T[];
  total: number;
  pageSize: number; // >0
  pageNo: number; // [1~total/pageSize+1]
  newDefaultRow?: () => T
};

export type Row<T> = {
  index: number;
  checked: boolean;
  rowData: T;
};

export const convToDataSource = <T>(
  rows: T[] = [],
  total?: number,
  newDefaultRow?: () => T,
  pageSize: number = 10,
  pageNo: number = 1,
): DataSource<T> => {
  return {
    rows: rows ?? [],
    newDefaultRow,
    total: total ? total : rows?.length ?? 0,
    pageSize,
    pageNo,
  };
};